;==============================================================================
; 完整测试：Bootloader 加载并跳转到内核
;==============================================================================
bits 16
org 0x7c00

KERNEL_OFFSET equ 0x1000
KERNEL_SECTORS equ 5

start:
    cli
    xor ax, ax
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov sp, 0x7c00
    mov [boot_drive], dl    ; 保存启动盘号
    sti
    
    ; 显示启动消息
    mov si, msg_boot
    call print
    
    ; 加载内核
    mov si, msg_load
    call print
    
    ; 重置磁盘
    mov ah, 0x00
    mov dl, [boot_drive]
    int 0x13
    jc disk_error
    
    ; 读取内核
    mov ah, 0x02
    mov al, KERNEL_SECTORS
    mov ch, 0
    mov cl, 2
    mov dh, 0
    mov dl, [boot_drive]
    mov bx, KERNEL_OFFSET
    int 0x13
    jc disk_error
    
    cmp al, KERNEL_SECTORS
    jne disk_error
    
    mov si, msg_ok
    call print
    
    ; 切换保护模式
    mov si, msg_pm
    call print
    
    cli
    in al, 0x92
    or al, 2
    out 0x92, al
    
    lgdt [gdt_descriptor]
    
    mov eax, cr0
    or eax, 1
    mov cr0, eax
    
    jmp 0x08:protected_mode

disk_error:
    mov si, msg_err
    call print
    jmp $

print:
    pusha
    mov ah, 0x0e
.loop:
    lodsb
    cmp al, 0
    je .done
    int 0x10
    jmp .loop
.done:
    popa
    ret

align 8
gdt_start:
    dq 0x0000000000000000
    dw 0xFFFF, 0x0000
    db 0x00, 0b10011010, 0b11001111, 0x00
    dw 0xFFFF, 0x0000
    db 0x00, 0b10010010, 0b11001111, 0x00
gdt_end:

gdt_descriptor:
    dw gdt_end - gdt_start - 1
    dd gdt_start

bits 32
protected_mode:
    mov ax, 0x10
    mov ds, ax
    mov ss, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov esp, 0x90000
    
    ; 清屏（蓝色）
    mov edi, 0xb8000
    mov ecx, 80 * 25
    mov ax, 0x1f20
    rep stosw
    
    ; 显示消息
    mov edi, 0xb8000
    mov esi, msg_jumping
    mov ah, 0x1f
.print_loop:
    lodsb
    cmp al, 0
    je .done_print
    stosw
    jmp .print_loop
.done_print:
    
    ; 跳转到内核
    mov eax, KERNEL_OFFSET
    jmp eax

msg_boot:    db 'Bootloader starting...', 13, 10, 0
msg_load:    db 'Loading kernel...', 13, 10, 0
msg_ok:      db 'OK', 13, 10, 0
msg_err:     db 'DISK ERROR!', 13, 10, 0
msg_pm:      db 'Entering PM...', 13, 10, 0
msg_jumping: db 'Jumping to kernel at 0x1000...', 0
boot_drive:  db 0

times 510 - ($ - $$) db 0
dw 0xaa55

